NBA moderna (1976-2011): VARIABILE DIPENDENTE: numero di vittorie in stagione COVARIATE: tutte le altre (o uno specifico insieme di queste, in base all’obiettivo di analisi) Considerare solo le squadre che hanno giocato 82 partite (dataset$games==82)
Con questo report ci siamo interessati allo studio di un modello lienare predittivo per le vittorie, basato sul numero di rimbalzi annuali effettuati dalle squadre nel campionato NBA. Vengono prese in considerazione solo le squadre con almeno 82 partite disputate, con riferimento agli anni dal 1976 al 2011.
La previsione del modello lineare e’ basata sull’uso di coefficienti ideati per essere il piu possibile significativi e conforme alla nostra idea di incidenza sulle vittorie di certe variabili riespetto ad altre.
I dettagli su come eseguire il programma e utilizzare la funzione predittiva si trovano direttamente di seguito, assieme al processo di realizzazione e verifica del modello stesso.
TODO: aggiungere descrizione per ogni grafico
filepath <- here("0_Materiale", "basketball_teams.txt")
dataset <- read.delim(filepath)
# str(dataset)
FIRST <- 1976 # primo anno del range da considerare per lo studio
LAST <- 2011 # ultimo anno del range da considerare per lo studio
df <- dataset [dataset$lgID=="NBA" & dataset$year >= FIRST & dataset$year <= LAST & dataset$games==82,]
df$reb <- df$o_reb + df$d_reb
# summary(df)
TODO: aggiungere descrizione per ogni grafico
TODO: aggiungere descrizione test
ad.test(df$reb)
##
## Anderson-Darling normality test
##
## data: df$reb
## A = 3.6997, p-value = 3.1e-09
Con un livello di significatività (\(\alpha\)) di 0.01 e un p-value molto piccolo (3.1e-09) ottenuto dal test di normalità di Anderson-Darling per i dati della variabile df$reb, puoi concludere che hai sufficiente evidenza statistica per respingere lipotesi nulla che i dati seguono una distribuzione normale.Con il tuo livello di significatività del 0.01 e il p-value molto piccolo (3.1e-09), il p-value è inferiore al livello di significatività, quindi respingeresti lipotesi nulla. Questo suggerisce che i dati nella variabile df$reb non seguono una distribuzione normale al livello di significatività del 0.01. In termini più pratici, hai abbastanza evidenza statistica per concludere che la variabile df$reb non segue una distribuzione normale basandoti sui risultati del test di Anderson-Darling.
TODO: Aggiungere descrizione test
ks.test(df$reb, "pnorm")
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: df$reb
## D = 1, p-value < 2.2e-16
## alternative hypothesis: two-sided
Il risultato che hai ottenuto riguarda il test di Kolmogorov-Smirnov a campione singolo sui dati contenuti nella variabile df$reb. Il test KS confronta la distribuzione empirica dei tuoi dati con una distribuzione teorica (spesso una distribuzione uniforme). In breve, il risultato suggerisce che i tuoi dati non seguono la distribuzione teorica presunta, e cè un elevata probabilità che la differenza osservata sia statisticamente significativa.
TODO: Aggiungere descrizione test
ks.test(df$reb, "pnorm")
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: df$reb
## D = 1, p-value < 2.2e-16
## alternative hypothesis: two-sided
In sintesi, il risultato del test di Shapiro-Francia indica che i tuoi dati nella variabile df$reb non seguono una distribuzione normale. Questo è supportato dal valore basso del p-value, il quale suggerisce che la differenza tra la distribuzione dei tuoi dati e una distribuzione normale è statisticamente significativa.
Dividiamo ora il nostro dataset in 2 parti, la parte train, ossia la parte che utilizzeremo per “addestrare” il nostro modello lineare, e la parte test, ossia una parte del dataset su cui testeremo il nostro modello lineare
sample <- sample(c(TRUE, FALSE), size = nrow(df), replace=TRUE, prob=c(0.7, 0.3))
train_df <- df[sample, ]
test_df <- df[!sample, ]
TODO: Aggiungere descrizione modello lineare
TODO: Aggiungere breve testo introduttivo
\(\text{Formula1} = \frac{\text{Rimbalzi offensivi in attacco}}{\text{Tiri sbagliati su azione}}\) Rappresenta la capacità della squadra di ripossesso della palla dopo un tiro che non va a canestro e colpisce il tabellone.
\(\text{Formula2} = \frac{\text{Rimbalzi difensivi in difesa presi}}{\text{Tiri sbagliati su azione degli avversari}}\) Rappresenta la capacità della squadra di impossessarsi della palla dopo un tiro sbagliato della squadra avversaria che colpisce il tabellone, che troviamo un buon stimatore della capacità di contropiede della squadra.
\(\text{Formula3} = \frac{\text{Palle riprese in attacco} + 1.5 \times \text{Palle riprese in difesa}}{\text{Palle perse in attacco} + 2 \times \text{Rimbalzi subiti in difesa}}\) Rappresenta il rapporto tra le palle riprese nei rimbalzi (sia offensivi che difensivi) rispetto alle palle perse nei rimbalzi (sia offensivi che difensivi). I coefficienti sono stati scelti in base a ciò che riteniamo più importante in una partita, ossia la difesa del proprio canestro.
\(\text{Formula4} = (\text{Palle riprese in attacco - Palle perse in attacco}) + 1.5*(\text{Palle riprese in difesa - Palle perse in difesa})\) Cresce all’aumentare dei rimbalzi ottenuti e diminuisce all’aumentare dei rimbalzi subiti, considerando anche un coefficiente che da particolare importanza alla difesa.
\(\text{Formula5} = \frac{(\frac{\text{Rimbalzi subiti in difesa}}{\text{Palle perse in difesa}})}{(\frac{\text{Rimbalzi subiti in attacco}}{\text{Palle perse in attacco}})}\) Mostra quanto siano influenti i rimbalzi nel rapporto tra le palle perse dalla squadra e le palle perse dagli avversari.
TODO: Aggiungere descrizione
train_df$f1 <- (train_df$o_oreb)/(train_df$o_fga-train_df$o_fgm)
train_df$f2 <- (train_df$d_dreb)/(train_df$d_fga-train_df$d_fgm)
train_df$f3 <- (train_df$o_oreb + 1.5 * train_df$d_dreb)/(train_df$o_dreb + 2 * train_df$d_oreb)
train_df$f4 <- (train_df$o_oreb - train_df$o_dreb) + 1.5 * (train_df$d_dreb - train_df$d_oreb)
train_df$f5 <- (train_df$d_oreb / train_df$d_to) / (train_df$o_dreb / train_df$o_to)
train_lm <- lm(won ~ f1 + f2 + f3 + f4 + f5, data = train_df)
summary (train_lm)
##
## Call:
## lm(formula = won ~ f1 + f2 + f3 + f4 + f5, data = train_df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -14.3106 -3.6844 0.0969 3.3092 15.6443
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 387.69949 21.44403 18.080 < 2e-16 ***
## f1 88.69539 11.83668 7.493 2.38e-13 ***
## f2 -51.88741 15.15701 -3.423 0.00066 ***
## f3 -271.44216 18.22374 -14.895 < 2e-16 ***
## f4 0.03170 0.00484 6.549 1.23e-10 ***
## f5 -178.37788 4.30384 -41.446 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.858 on 608 degrees of freedom
## Multiple R-squared: 0.8514, Adjusted R-squared: 0.8502
## F-statistic: 696.7 on 5 and 608 DF, p-value: < 2.2e-16
TODO: Aggiungere presentazione grafici
TODO: Introduzione a perché normalizzare i dati
train_df$f1_z <- scale(train_df$f1)
train_df$f2_z <- scale(train_df$f2)
train_df$f3_z <- scale(train_df$f3)
train_df$f4_z <- scale(train_df$f4)
train_df$f5_z <- scale(train_df$f5)
train_lm_z <- lm(won ~ f1_z + f2_z + f3_z + f4_z + f5_z, data = train_df)
summary(train_lm_z)
##
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z, data = train_df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -14.3106 -3.6844 0.0969 3.3092 15.6443
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 40.4625 0.1961 206.368 < 2e-16 ***
## f1_z 2.8111 0.3751 7.493 2.38e-13 ***
## f2_z -2.4752 0.7230 -3.423 0.00066 ***
## f3_z -17.4851 1.1739 -14.895 < 2e-16 ***
## f4_z 8.5174 1.3005 6.549 1.23e-10 ***
## f5_z -12.4911 0.3014 -41.446 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.858 on 608 degrees of freedom
## Multiple R-squared: 0.8514, Adjusted R-squared: 0.8502
## F-statistic: 696.7 on 5 and 608 DF, p-value: < 2.2e-16
TODO Aggiungere introduzione
summary (train_lm_z)
##
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z, data = train_df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -14.3106 -3.6844 0.0969 3.3092 15.6443
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 40.4625 0.1961 206.368 < 2e-16 ***
## f1_z 2.8111 0.3751 7.493 2.38e-13 ***
## f2_z -2.4752 0.7230 -3.423 0.00066 ***
## f3_z -17.4851 1.1739 -14.895 < 2e-16 ***
## f4_z 8.5174 1.3005 6.549 1.23e-10 ***
## f5_z -12.4911 0.3014 -41.446 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.858 on 608 degrees of freedom
## Multiple R-squared: 0.8514, Adjusted R-squared: 0.8502
## F-statistic: 696.7 on 5 and 608 DF, p-value: < 2.2e-16
summary_linModNormalized <- summary(train_lm_z)
r_squared <- summary_linModNormalized$r.squared
cat("R-squared:", r_squared, "\n")
## R-squared: 0.8514022
n <- length(df$o_oreb)
k <- length(train_lm_z$coefficients) - 1
adjusted_r_squared <- 1 - ((1 - r_squared) * (n - 1) / (n - k - 1))
cat("Adjusted R-squared:", adjusted_r_squared, "\n")
## Adjusted R-squared: 0.8505124
shapiro.test(residuals(train_lm_z))
##
## Shapiro-Wilk normality test
##
## data: residuals(train_lm_z)
## W = 0.99625, p-value = 0.1561
bptest(train_lm_z)
##
## studentized Breusch-Pagan test
##
## data: train_lm_z
## BP = 2.1642, df = 5, p-value = 0.826
car::vif(train_lm_z)
## f1_z f2_z f3_z f4_z f5_z
## 3.654844 13.576629 35.787242 43.925891 2.358866